﻿#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <errno.h>

#include "redis_client.h"
#include "yxjmj_conf.h"
#include "game_log.h"
#include "server.h"
#include "proto.h"
#include "client.h"
#include "player.h"
#include "room.h"

std::map<int, int(Server::*)(Client*)> Server::_hall_route =
{
{ SYS_ECHO ,&Server::heartbeat },
{ HEART_BEAT ,&Server::heartbeat },
{ CLIENT_OPEN_ROOM_REQ ,&Server::create_room },
{ CLIENT_JOIN_ROOM_REQ ,&Server::joinin_room }
};

TcpClient * Server::NewConnect(int fd)
{
	Client *client = new (std::nothrow) Client(fd);
	return client;
}

int Server::heartbeat(Client * client)
{
	Jpacket packet;
	packet.val = client->packet.val;
	packet.end();
	return client->send(packet.tostring());
}

int Server::create_room(Client * client)
{
	int ret = add_player(client);
	GAME_LOG.debug("dispatch ret=%d.", ret);
	if (ret == -1) {
		return -1;
	}
	else if (ret == -2) {
		send_error(client, 54, "您已被管理员封号!");
		return 0;
	}
	else if (ret == 1) {
		return 0;
	}
	else if (ret == 2) {
		return 0;
	}
	return handler_open_room(client);
}

int Server::joinin_room(Client * client)
{
	int ret = add_player(client);
	GAME_LOG.debug("dispatch ret=%d.", ret);
	if (ret == -1) {
		return -1;
	}
	else if (ret == -2) {
		send_error(client, 54, "您已被管理员封号!");
		return 0;
	}
	else if (ret == 1) {
		return 0;
	}
	else if (ret == 2) {
		return 0;
	}
	return handler_join_room(client);
}

Server::Server()
{
}

Server::~Server()
{
}

int Server::start()
{
	if (YXJMJ_CONF._game_flag > 1000000)
	{
		init_table();
	}
		
	init_accept(YXJMJ_CONF._loop, YXJMJ_CONF._port);
    return 0;

}

bool Server::return_room_pwd(int pwd)
{
	auto predis = Singleton<RedisClient>::Instance();
	int ret = predis->command("eval %s %d %s %d",
		YXJMJ_CONF._return_room_script.c_str(),
		2,
		"ROOM_PASSWORD",
		pwd);
	if (ret == 0)
	{
		GAME_LOG.debug("eval %s %d %s %d",
			YXJMJ_CONF._return_room_script.c_str(),
			2,
			"ROOM_PASSWORD",
			pwd);
		if (predis->reply->type == REDIS_REPLY_INTEGER && predis->reply->integer == 0)
		{
			return true;
		}
	}
	else
	{
		GAME_LOG.error("eval %s %d %s %d",
			YXJMJ_CONF._return_room_script.c_str(),
			2,
			"ROOM_PASSWORD",
			pwd);
	}
	return false;
}

int Server::init_table()
{
	if (YXJMJ_CONF._game_flag > 1000000)
	{
		//如果是金币场 预分配1000个桌子
		_rooms.MallocRooms(1000);
	}
	return 0;
}

void Server::del_client(Client *client)
{
    if (!CancelFd(client->fd))
    {
        GAME_LOG.error("free client err[miss]\n");
        return;
    }
	
	if (client->player)
	{
	    Player *player = client->player;
           
		if (client->position == POSITION_WAIT)
		{
			if (offline_players.find(player->uid) != offline_players.end())
			{
				offline_players.erase(player->uid);
			}
			if (online_players.find(player->uid) != online_players.end())
		    {
		        online_players.erase(player->uid);
		    }
			
			delete player;
		}
		else if (client->position == POSITION_TABLE)
		{
			if (online_players.find(player->uid) != online_players.end())
		    {	
		        GAME_LOG.debug("del client!, but client position is POSITION_TABLE.\n");
                GAME_LOG.debug("now move from oneline to offline.\n");
		        online_players.erase(player->uid);
				offline_players[player->uid] = client->player;
                //player->start_offline_timer();
                
				if (update_db_player_online(player->uid, YXJMJ_CONF._server_id, player->roomid, 0) < 0)
				{
					GAME_LOG.error("player off line, update db error.\n");
				}
				if (update_gold_room_player_count(YXJMJ_CONF._server_id, YXJMJ_CONF._server->count_server_player_num()))
				{
					GAME_LOG.fatal("player off line,  update_gold_room_player_count.error\n");
				}

				player->online = 0;
				player->client = NULL;
		    }
			client->player->client = NULL;
            //del_player(player);
		}	
	}	
	delete client;
}

int Server::dispatch(TcpClient *tcpclient)
{
	Client* client = (Client*)tcpclient;
	int cmd = client->command();
	if (cmd < 0)
	{
		GAME_LOG.error("the cmd format is error. parse cmd id < 0.\n");
		return -1;
	}
	//先筛选大厅协议
	auto hall_itr = _hall_route.find(cmd);
	if (hall_itr != _hall_route.end())
	{
		auto func = hall_itr->second;
		return (this->*func)(client);
	}

// 	反射指令，用于测试网络连通性
// 		if (cmd == SYS_ECHO)
// 		{
// 			Jpacket packet;
// 			packet.val = client->packet.val;
// 			packet.end();
// 			return client->send(packet.tostring());
// 		
// 			return 0;
// 		}	
// 		
// 		//心跳，也可用于网络测速
// 		if (cmd == HEART_BEAT)
// 		{
// 			Jpacket packet;
// 			packet.val = client->packet.val;
// 			packet.end();
// 			return client->send(packet.tostring());
// 		}
// 			
// 		//玩家开房
// 		if (cmd == CLIENT_OPEN_ROOM_REQ)
// 		{
// 			int ret = add_player(client);
// 				GAME_LOG.debug("dispatch ret=%d.", ret);
// 			if (ret == -1) {
// 				return -1;
// 			} else if (ret == -2) {
// 				send_error(client, 54, "您已被管理员封号!");
// 				return 0;
// 			}else if (ret == 1) {
// 				return 0;
// 			} else if (ret == 2) {
// 				return 0;
// 			}
// 			return handler_open_room(client);		
// 		}
// 		
// 		//玩家加入指定房间游戏
// 		if (cmd == CLIENT_JOIN_ROOM_REQ)
// 		{
// 			int ret = add_player(client);			
// 				GAME_LOG.debug("dispatch ret=%d.", ret);
// 			if (ret == -1) {
// 				return -1;
// 			} else if (ret == -2){			
// 				send_error(client, 54, "您已被管理员封号!");
// 				return 0;
// 			}else if (ret == 1) {
// 				return 0;
// 			} else if (ret == 2) {
// 				return 0;
// 			}
// 			return handler_join_room(client);
// 		}
	
	if (safe_check(client, cmd) < 0)
	{
		return -1;
	}
	
	Player *player = client->player;
	auto room = _rooms[player->roomid];
	//筛选游戏协议
	auto game_itr = room->_game_route.find(cmd);
	if (game_itr == room->_game_route.end())
	{
		GAME_LOG.error("invalid command[%d]\n", cmd);
		return -1;
	}
	else
	{
		auto func = game_itr->second;
		(room->*func)(player);
	}
	return 0;

// 	switch (cmd)
// 	{
// 	//客户端网络测试返回
// 		//暗杠
// 	case CLIENT_ANG_GANG_REQ:
// 		room->handler_player_operater_ANG_GANG(player);
// 		break;
// 		//明杠 有判断抢杠胡*
// 	case CLIENT_MING_GANG_REQ:
// 		room->handler_player_operater_MING_GANG(player);
// 		break;
// 		//自摸
// 	case CLIENT_ZIMO_HU_REQ:
// 		room->handler_player_operater_ZI_MO(player);
// 		break;
// 		//出牌
// 	case CLIENT_OUT_MJ_REQ:
// 		room->handler_player_operater_PUTOUT_MJ(player);
// 		break;
// 		//碰
// 	case CLIENT_PENG_REQ:
// 		room->handler_player_operater_PENG(player);
// 		break;
// 		//放杠
// 	case CLIENT_FANG_GANG_REQ:
// 		room->handler_player_operater_FANG_GANG(player);
// 		break;
// 		//放炮胡
// 	case CLIENT_FANG_PAO_HU_REQ:
// 		room->handler_player_operater_FANG_PAO_HU(player);
// 		break;
// 	case CLIENT_QIANG_GANG_HU_REQ:
// 		room->handler_player_operater_QIANG_GANG_HU(player);
// 		break;
// 	case CLIENT_PASS_REQ:
// 		room->handler_player_operater_PASS(player);
// 		break;
// 	case CLIENT_PASS2_REQ:
// 		room->handler_player_operater_PASS2(player);
// 		break;
// 	case CLIENT_DISSOLUTION_ROOM_REQ:
// 		room->handler_player_dissolution_room_req(player);
// 		break;
// 	case CLIENT_DISSOLUTION_ROOM_CONFIRM:
// 		room->handler_player_dissolution_room_confirm(player);
// 		break;
// 	case CLIENT_READY_REQ:
// 		room->handler_player_ready(player);
// 		break;
// 	case CLIENT_NOLMAL_CHART_REQ:
// 		room->handler_nolmal_chart_req(player);
// 		break;
// 	case CLIENT_SPEAK_REQ:
// 		room->handler_speak_req(player);
// 		break; 
// 	case CLIENT_DING_QUE_REQ:
// 		room->handler_ding_que_req(player);
// 		break;
// 	case CLIENT_BAO_TING_REQ:
// 		room->handler_bao_ting_req(player);
// 		break;
// 	case CLIENT_GOLDROOM_LOGOUT_ROOM:
// 		del_player(player);
// 		break;
// 	case CLIENT_CANCEL_ROBOT_OP_REQ:
// 		room->handler_cancel_robot_op(player);
// 		break;
// 	case CLIENT_ROBOT_AUTO_OUT_MJ_REQ:
// 		room->handler_robot_auto_out_mj(player);
// 		break;
// 
// 	default:
// 		GAME_LOG.error("invalid command[%d]\n", cmd);
// 		return -1;
// 	}	
	return 0;
}

int Server::safe_check(Client *client, int cmd)
{
	if (online_players.find(client->uid) == online_players.end())
	{
		GAME_LOG.error("player[%d] must be online player.\n", client->uid);
		return -1;
	}
	
	Player *player = client->player;
	if (_rooms[player->roomid] == nullptr)
	{
		GAME_LOG.error("safe_check uid[%d] is not in table[%d].\n", player->uid, player->roomid);
		return -1;
	}
	
	return 0;
}


int Server::handler_open_room(Client *client)
{	
	//判断是不是可开房
	if (YXJMJ_CONF._game_flag > 1000000)
	{
		GAME_LOG.error("only kaifang room can open room.\n");
		return 0;
	}
	
	Player *player = client->player;
	Json::Value &val = client->packet.tojson();
	
	int ticket_id = val["ticket_id"].asInt();		//开房序号
	int password = val["password"].asInt();	//房间密码
	//如果当前连接没有对应的玩家数据
	if (client->player == NULL)
	{
		GAME_LOG.error("handler_open_room, client->player = NULL.\n");
		return -1;
	}
	//如果拿不到房间信息
	S_DB_TICKET_INFO ticket_info;
	if (0 != get_room_ticket_board_num(ticket_info, ticket_id))
	{
		GAME_LOG.error("ticket_info error. [%d]\n", ticket_id);
		return -1;
	}
	//如果房间状态
	if (ticket_info.status != 1)
	{
		GAME_LOG.error("ticket_status error. [%d]\n", ticket_id);
		return -1;
	}
	//密码不对
	if (password != ticket_info.pwd)
	{
		GAME_LOG.error("ticket_pwd error. [%d]\n", password);
		return -1;
	}
	//如果游戏人数不对
	if (ticket_info.player_num < 2 || ticket_info.player_num > 4)
	{
		GAME_LOG.error("player_num: %d, must 2 or 3 or 4 \n", ticket_info.player_num);
		return -1;
	}

	//如果用户的状态是已经在座位上了
	if (client->position == POSITION_TABLE)
	{
		GAME_LOG.error("handler_open_room uid[%d] have been in table\n", player->uid);
		return 0;
	}

	Room *room = _rooms.CreateNewRoom();
	int roomid = room->roomid;
	if ( room->init_private(ticket_info.board_num, ticket_info.player_num ) < 0 )
	{
		GAME_LOG.error("roomid[%d] init error2.\n",roomid);
		send_error(client, 51, "创建房间失败.");	
		_rooms.DestoryRoom(roomid);
		return -1;
	}
	//如果房间状态不能被修改
	if (update_room_ticket_status(ticket_id, 2) != 0)
	{
		GAME_LOG.error("ticket_fix_status[%d] error\n", ticket_id);
		_rooms.DestoryRoom(roomid);
		return -1;
	}
	//取消定时系统
	room->_has_timer = false;
	room->password = password;
	room->rec_id = ticket_id;
	room->priv_uid = ticket_info.uid;
	room->clubid = ticket_info.clubid;
	//如果进入不了房间
	if ( room->player_enter_room(player) < 0)
	{
		GAME_LOG.error("creater enter room error.\n");
		_rooms.DestoryRoom(roomid);
		return -1;
	}
	// 刷新房间人数
	if (!Singleton<RedisClient>::Instance()->
		hset("ROOM_PLAYER_NUM", to_string(ticket_id), to_string(room->players.size())))
	{
		_rooms.DestoryRoom(roomid);
		return -1;
	}
	if (0 != bind_room_ticket(ticket_id,YXJMJ_CONF._server_id, roomid))
	{
		_rooms.DestoryRoom(roomid);
		return -1;
	}
	return 0;
}

int Server::handler_join_room(Client *client)
{
	//加入一个收费房间
	if (YXJMJ_CONF._game_flag < 1000000)
	{
		Player *player = client->player;	
		if (client->position == POSITION_TABLE)
		{
			GAME_LOG.error("handler_join_room uid[%d] have been in table.\n", player->uid);
			return 0;
		}
		

		Json::Value &val = client->packet.tojson();
		int roomid = val["roomid"].asInt();
		Room *room = _rooms[roomid];
		if (room == nullptr)
		{
			GAME_LOG.error("handler_join_room, but room not create.\n", player->uid);
			send_error(client, 53, "房间号有误");
			return -1;
		}
		
		if (room->player_enter_room(player) < 0)
		{
			return -1;
		}
		Singleton<RedisClient>::Instance()->
			hset("ROOM_PLAYER_NUM", to_string(room->rec_id), to_string(room->players.size()));
		
	}
	else
	//加入一个普通房间
	{
		Player *player = client->player;
		
		int min_access_gold = 0;
		int max_access_gold = 0;
		//是金币场
		if (YXJMJ_CONF._game_flag/1000000 == 1)
		{
			min_access_gold = YXJMJ_CONF._min_access;
			max_access_gold = YXJMJ_CONF._max_access;
			if (player->robot_flag != 1)
			{
				if (player->gold < min_access_gold)
				{
					GAME_LOG.debug("gold_room handler_join_table, uid[%d] mygold[%d] needgold[%d], gold not enought.\n",player->uid, player->gold, min_access_gold);
					send_error(client, 50, "对不起，您的金币不足，请\n使用钻石兑换金币。");
					return -1;
				}
				if (max_access_gold != 0 && player->gold >= max_access_gold)
				{				
					GAME_LOG.debug("gold_room handler_join_table, uid[%d] mygold[%d] max_access_gold[%d], gold too big.\n",player->uid, player->gold, max_access_gold);
					send_error(client, 50, "对不起，您的金币过高，请\n前往高级场次参与游戏。");
					return -1;
				}
			}
		}
		else if (YXJMJ_CONF._game_flag == 2000001)
		{	
			min_access_gold = YXJMJ_CONF._min_access;
			max_access_gold = YXJMJ_CONF._max_access;
			if (player->robot_flag != 1)
			{
				if (player->diamonds < min_access_gold)
				{
					GAME_LOG.debug("gold_room handler_join_table, uid[%d] mydiamonds[%d] needdiamonds[%d], diamonds not enought.\n",player->uid, player->diamonds, min_access_gold);
					send_error(client, 50, "对不起，您的钻石不足，请\n去商场充值钻石。");
					return -1;
				}
			}
		}
		//如果用户状态是在坐
		if (client->position == POSITION_TABLE)
		{
			GAME_LOG.debug("gold_room handler_join_table uid[%d] have been in table\n", player->uid);
			return -1;
		}	
		//机器人不能进入有3个人的房间
		Room* room;
		if (client->player->robot_flag != 1)
		{
			room = _rooms.MatchingRoom();
		}
		else
		{
			room = _rooms.MatchingRoom(3);
		}
		if (room == nullptr)
		{
			GAME_LOG.error("no seat\n");
			return -1;
		}
		if (room->players.find(player->uid) != room->players.end())
		{
			_rooms.LeaveRoom(room->roomid);
			GAME_LOG.error("handler_join_table uid[%d] is in room[%d]\n", player->uid, player->roomid);
			return -1;
		}
		client->set_positon(POSITION_TABLE);
		online_players[player->uid] = player;
		room->player_enter_room(player);
		return 0;

	}	
	return 0;
}

int Server::add_player(Client *client)
{
	Json::Value &val = client->packet.tojson();
	int uid = val["uid"].asInt();
	client->uid = uid;
	
	// 如果这个用户是在线状态的话
	// 好像是踢掉上一个用户
	if (online_players.find(uid) != online_players.end())
	{
		Player *player = online_players[uid];
		GAME_LOG.debug("online_players uid[%d]\n",player->uid);
	
		//找到当前在线的用户如果没在桌上就直接踢掉
		if (_rooms[player->roomid] == nullptr)
		{
			GAME_LOG.error("rebind by online uid[%d] is not in table[%d]\n", player->uid, player->roomid);
			//如果这个连接没有获取过用户信息
			if (client->player == NULL)
			{			
				//将这个用户的所有权给另外一个连接
				player->set_client(client);
				// 重新获取用户信息
				int ret = player->init();
				if (ret == -1)
				{		
					GAME_LOG.error("init_player error. [%d]\n",ret);
					return -1;
				}							
			}
			//这个是要舍弃旧的连接
			Client *oldClient = player->client;
			if (oldClient != client) {
				_fd_clients.erase(oldClient->fd);
				delete oldClient;
				player->set_client(client);
			}	
			
			return 0;
		}
		//如果当前用户在桌上
		Client *oldClient = player->client;
		//是不是同一个连接
		if (oldClient == client )
		{
			GAME_LOG.info("oldClient:%d, client:%d\n", oldClient->fd, client->fd);
			player->set_client(client);
			client->set_positon(POSITION_TABLE);
			_rooms[player->roomid]->handler_rebind(player);
			return 2;
		}
		//一个新连接进来了
		GAME_LOG.debug("old client fd:%d, player->uid:%d.\n",oldClient->fd, player->uid);
	    player->set_client(client);
		client->set_positon(POSITION_TABLE);		
		_rooms[player->roomid]->handler_rebind(player);
		
		//在桌位上的时候如果被挤下来了会通知旧连接
		Jpacket packet;
	    packet.val["cmd"] = SERVER_LOGIN_OTHER_DEVICE;
		packet.val["uid"] = uid;
	    packet.end();
		GAME_LOG.info("SERVER_LOGIN_OTHER_DEVICE.\n");
	    oldClient->send(packet.tostring());
		
		//旧连接预杀死
		oldClient->player = NULL;
		oldClient->pre_destroy();
	    return 2;
	}

	/* rebind by offline */
	//如果这个用户是离线状态
	if (offline_players.find(uid) != offline_players.end())
	{
		Player *player = offline_players[uid];
		GAME_LOG.debug("offline_players uid[%d]\n",player->uid);
		//如果没在房间里
		if (_rooms[player->roomid] == nullptr)
		{
			GAME_LOG.error("rebind by offline uid[%d] is not in table[%d]\n", player->uid, player->roomid);
			if (client->player == NULL)
			{
				player->set_client(client);
				int ret = player->init();
				if (ret < 0)
				{
					GAME_LOG.error("init_player error.[%d]\n",ret);
					return -1;
				}
			}
			//将用户转移到在线用户
			offline_players.erase(uid);
    		online_players[uid] = player;
			//老client直接杀
			Client *oldClient = player->client;
			if (oldClient != client) {
				_fd_clients.erase(oldClient->fd);
				delete oldClient;
				player->set_client(client);
			}	
			return 0;
		}
        //在房间里的话就直接获取所有权
    	offline_players.erase(uid);
    	online_players[uid] = player;
    	player->set_client(client);
		client->set_positon(POSITION_TABLE);
		_rooms[player->roomid]->handler_rebind(player);
	    return 1;
	}

    //没登录过的萌新
    /* set player info */
    Player *player = new (std::nothrow) Player();
	if (player == NULL)
    {
		GAME_LOG.error("new player err");
		return -1;
    }
	
   	player->set_client(client);
	int ret = player->init();
	if (ret == -1)
	{		
		GAME_LOG.error("init_player error. [%d]\n",ret);
		return -1;
	}				
	else if (ret == -2)
	{
		GAME_LOG.error("init_player error. [%d]\n",ret);
		return -2;
	}
    return 0;
}

int Server::del_player(Player *player)
{
	int ret;
	
	if (YXJMJ_CONF._game_flag > 1000000)
	{
		ret = _rooms[player->roomid]->handler_logout(player);
		if ( ret < 0 )
		{
			return -1;
		}
	}

	
	ret = _rooms[player->roomid]->del_player(player);
	if (ret < 0)
	{
		GAME_LOG.error("del player[%d], in room error.\n",player->uid);
		return -1;	
	}
	
	if (offline_players.find(player->uid) != offline_players.end())
	{
    	offline_players.erase(player->uid);
        GAME_LOG.info("erase offline player[%d].\n", player->uid);
	}
	
	if (online_players.find(player->uid) != online_players.end())
	{
	    GAME_LOG.info("erase online player[%d].\n", player->uid);
    	online_players.erase(player->uid);
	}

	if (update_db_player_online(player->uid, YXJMJ_CONF._server_id, player->roomid , 0) < 0)
	{
		GAME_LOG.fatal("del_player, update db error.\n");
	}
	if ( update_gold_room_player_count(YXJMJ_CONF._server_id, YXJMJ_CONF._server->count_server_player_num()))
	{
		GAME_LOG.fatal("del_player,  update_gold_room_player_count.error\n");
	}
	player->online = 0;

	if (YXJMJ_CONF._game_flag > 1000000 )
	{
		if ( update_room(player->roomid) < 0)
		{
			GAME_LOG.error("del_player, update table error.\n");
			return -1;	
		}
	}
	
	player->stop_offline_timer();
	player->stop_pass_timer();
	player->stop_auto_outmj_timer();
	player->stop_qiangganghu_timer();
	
	if (player->client)
	{
		Client *client = player->client;
		client->position = POSITION_WAIT;
		client->pre_destroy();
		client->player = NULL;
		delete player;
		return 0;
	}
	
    delete player;	

    return 0;
}

int Server::update_room(int rid)
{
    GAME_LOG.debug("update_table.\n");
	if (_rooms.LeaveRoom(rid))
	{
		return 0;
	}
	return -1;
}


int Server::dissolution_room_del_player(Player *player)
{
	int ret;
	if (player == NULL || player->roomid == 0) {
		GAME_LOG.fatal("dissolution_room_del_player.\n");
		return -1;
	}
	ret = _rooms[player->roomid]->del_player(player);
	if (ret < 0)
	{
		GAME_LOG.error("del player[%d], in room error.\n",player->uid);
		return -1;	
	}
	
	if (offline_players.find(player->uid) != offline_players.end())
	{
    	offline_players.erase(player->uid);
        GAME_LOG.info("erase offline player[%d].\n", player->uid);
	}
	
	if (online_players.find(player->uid) != online_players.end())
	{
	    GAME_LOG.info("erase online player[%d].\n", player->uid);
    	online_players.erase(player->uid);
	}

	if ( update_db_player_online(player->uid, YXJMJ_CONF._server_id, player->roomid, 0) < 0 )
	{
		GAME_LOG.fatal("del_player, update db error.\n");
	}
	if ( update_gold_room_player_count(YXJMJ_CONF._server_id, YXJMJ_CONF._server->count_server_player_num()))
	{
		GAME_LOG.fatal("del_player,  update_gold_room_player_count.error\n");
	}
	player->online = 0;
	
	player->stop_offline_timer();
	player->stop_pass_timer();
	player->stop_auto_outmj_timer();
	player->stop_qiangganghu_timer();
	
	if (player->client)
	{
		Client *client = player->client;
		client->position = POSITION_WAIT;
		client->pre_destroy();
		client->player = NULL;
		delete player;
		return 0;
	}
    delete player;	

    return 0;
}


int Server::dissolution_room(int roomid)
{
	Room *room = _rooms[roomid];
	if (room == nullptr)
	{
		GAME_LOG.error("dissolution room, no this room[%d].\n", roomid);
		return -1;
	}
	room->del_all_players();
	bind_room_ticket(room->rec_id, 0, 0);
	Singleton<RedisClient>::Instance()->
		hdel("ROOM_PLAYER_NUM", to_string(room->rec_id));
	GAME_LOG.info("erase room[%d] in _rooms.\n",roomid); 
	_rooms.DestoryRoom(roomid);
	GAME_LOG.info("delete room[%d] succ.\n", roomid);
	return 0;
}

int Server::send_error(Client *client, int error_code, std::string err_msg)
{
    Jpacket error;
    error.val["cmd"] = SERVER_ERROR_UC;
    error.val["err"] = error_code;
	error.val["err_msg"] = err_msg;
    error.end();
	GAME_LOG.info("SERVER_ERROR_UC.\n");
    return client->send(error.tostring());
}


int Server::count_server_player_num()
{
	return online_players.size() + offline_players.size();
}
